package com.zmn.oms.dubbo.impl.zmn.normal.order;

import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.google.common.collect.Lists;
import com.zmn.base.product.common.consts.BaseProductConsts;
import com.zmn.base.product.common.dto.product.ProductBaseQuery;
import com.zmn.base.product.common.dto.product.ec.ProductBaseDRO;
import com.zmn.base.product.dubbo.interfaces.product.foreign.ProductForeignListRemoteService;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.oms.business.interfaces.grid.GridGroupDistributeBService;
import com.zmn.oms.common.constant.OrderGateTypeConsts;
import com.zmn.oms.common.dio.schedule.GridGroupScheduleCheckDIO;
import com.zmn.oms.common.dro.schedule.GridGroupScheduleCheckDRO;
import com.zmn.oms.dubbo.dto.zmn.order.*;
import com.zmn.oms.dubbo.dto.zmn.orderstock.StockScheduleTimeDIO;
import com.zmn.oms.dubbo.interfaces.zmn.normal.order.ZsNormalOrderWorkScheduleRemoteService;
import com.zmn.oms.dubbo.utils.DubboConsts;
import com.zmn.oms.model.bo.stock.StockDefaultDutyTimeQueryBO;
import com.zmn.oms.model.bo.stock.StockScheduleTimeBO;
import com.zmn.oms.model.vo.work.schedule.OrderScheduleVO;
import com.zmn.oms.model.vo.work.schedule.ScheduleDayVo;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkScheduleBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkStockScheduleBService;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

/**
 * 类描述：普通单预约时间
 *
 * @author liuying
 * @date 2019/01/08 15:35
 */
@Service(loadbalance = "roundrobin", timeout = 5000, retries = 2, version = DubboConsts.INTERFACE_VERSION, validation = "false")
public class ZsNormalOrderWorkScheduleRemoteServiceImpl implements ZsNormalOrderWorkScheduleRemoteService {

    private static final String TAG = "啄木鸟-普通单-预约时间";
    private Logger logger = LoggerFactory.getLogger(ZsNormalOrderWorkScheduleRemoteServiceImpl.class);

    @Autowired
    private ZsOrderWorkScheduleBService zsOrderWorkScheduleBService;
    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private ZsOrderWorkStockScheduleBService zsOrderWorkStockScheduleBService;
    @Autowired
    private GridGroupDistributeBService gridGroupDistributeBService;

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private ProductForeignListRemoteService productForeignListRemoteService;

    @NacosValue(value = "${schedule.time.stock.city:''}", autoRefreshed = true)
    private String stockCity;
    @NacosValue(value = "${schedule.time.stock.open.entrance:''}", autoRefreshed = true)
    private String stockOpenEntrance;


    @Override
    public ResponseDTO<Boolean> isApplyStock(StockWhiteDIO stockWhiteDIO) {
        logger.info("ZsNormalOrderWorkScheduleRemoteServiceImpl.isWhiteByAllConditions stockWhiteDIO={}", stockWhiteDIO);
//        StockWhiteDTO stockWhiteDTO = StockWhiteDTO
//                .builder()
//                .workCityId(stockWhiteDIO.getCityId())
//                .masterId(Optional.ofNullable(stockWhiteDIO.getMasterId()).orElse(GlobalConsts.YES))
//                .build();
//        return ResponseDTO.success(orderStockBService.isWhiteByAllConditions(stockWhiteDTO));
        return ResponseDTO.success(this.isWhiteWorkCity(stockWhiteDIO.getCityId(), stockWhiteDIO.getGeteType()));
    }

    private boolean isWhiteWorkCity(Integer cityId, Integer geteType) {
        geteType = Optional.ofNullable(geteType).orElse(OrderGateTypeConsts.GATE_USER);

        // 判断入口是否开启
        if (StringUtil.isBlank(stockOpenEntrance)) {
            return false;
        }
        List<String> stockOpenEntranceList = Arrays.asList(stockOpenEntrance.split(","));
        if (!stockOpenEntranceList.contains(geteType.toString())) {
            return false;
        }

        // 判断城市
        if (NumberUtil.isNullOrZero(cityId)) {
            return false;
        }
        if (StringUtil.isBlank(stockCity)) {
            return true;
        }
        List<String> strings = Arrays.asList(stockCity.split(","));
        return strings.contains(String.valueOf(cityId));
    }

    @Override
    public ResponseDTO<List<OrderScheduleDayDRO>> getScheduleDayList() {
        try {
            logger.debug(String.format("%s#获取预约时间", TAG));
            List<ScheduleDayVo> scheduleDayVoList = zsOrderWorkScheduleBService.getScheduleDayList();
            List<OrderScheduleDayDRO> droList = BeanMapper.mapList(scheduleDayVoList, OrderScheduleDayDRO.class);
            return ResponseDTO.success(droList);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseDTO.fail(e.getMessage());
        }
    }

    @Override
    public ResponseDTO<OrderScheduleTimeDRO> getScheduleTimes(String scheDate) {
        try {
            Objects.requireNonNull(scheDate, "预约日期不能为空");
            OrderScheduleVO orderScheduleVO = zsOrderWorkScheduleBService.getScheduleTimes(scheDate, null);
            OrderScheduleTimeDRO orderScheduleTimeDRO = BeanMapper.map(orderScheduleVO, OrderScheduleTimeDRO.class);
            return ResponseDTO.success(orderScheduleTimeDRO);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseDTO.fail(e.getMessage());
        }
    }

    /**
     * 预约时间列表 48个时刻点
     *
     * @param orderScheduleDIO
     * @return
     */
    @Override
    public ResponseDTO<OrderScheduleTimeDRO> getScheduleTimesAndCheckStock(OrderScheduleDIO orderScheduleDIO) {
        if (StringUtils.isBlank(orderScheduleDIO.getScheDate())) {
            return ResponseDTO.fail("预约日期不能为空");
        }

        OrderScheduleVO orderScheduleVO = zsOrderWorkScheduleBService.getScheduleTimes(orderScheduleDIO.getScheDate(), null);
        OrderScheduleTimeDRO orderScheduleTimeDRO = BeanMapper.map(orderScheduleVO, OrderScheduleTimeDRO.class);
        return ResponseDTO.success(orderScheduleTimeDRO, "成功");
    }

    /**
     * 默认预约时间
     *
     * @param plat
     * @param geteType
     * @return
     * @see OrderGateTypeConsts
     */
    @Override
    public ResponseDTO<String> defaultScheduleTime(Integer plat, Integer geteType) {

        if (NumberUtil.isNullOrZero(geteType)) {
            geteType = OrderGateTypeConsts.GATE_USER;
        }
        String defaultDutyTime = zsOrderWorkScheduleBService.getDefaultHalfPointDutyTime(plat, geteType);

        return ResponseDTO.success(defaultDutyTime);
    }

    @Override
    public ResponseDTO<List<OrderCartScheduleTimeDRO>> listOrderCartScheduleTime(List<OrderCartScheduleDIO> orderScheduleList) {
        if (CollectionUtil.isNullOrEmpty(orderScheduleList)) {
            return ResponseDTO.fail("order cart list dio is empty");
        }

        List<OrderCartScheduleTimeDRO> listDRO = Lists.newArrayListWithCapacity(orderScheduleList.size());
        for (OrderCartScheduleDIO orderCartSchedule : orderScheduleList) {
            OrderCartScheduleTimeDRO orderCartScheduleTimeDRO = new OrderCartScheduleTimeDRO();
            Integer geteType = Optional.ofNullable(orderCartSchedule.getGeteType()).orElse(OrderGateTypeConsts.GATE_USER);

            String defaultDutyTime = zsOrderWorkScheduleBService.getDefaultHalfPointDutyTime(orderCartSchedule.getPlat(), geteType);
            orderCartScheduleTimeDRO.setDutyTime(defaultDutyTime);
            orderCartScheduleTimeDRO.setDutyTimestamp(DateUtil.toTimestampMillis(defaultDutyTime, DateUtil.FORMAT_DEFAULT));
            orderCartScheduleTimeDRO.setServCategId(orderCartSchedule.getServCategId());
            orderCartScheduleTimeDRO.setShowProductId(orderCartSchedule.getShowProductId());
            listDRO.add(orderCartScheduleTimeDRO);
        }
        return ResponseDTO.success(listDRO);
    }

    /**
     * 预约时间列表 96个时刻点
     * @param stockScheduleTimeDIO
     * @return
     */
    @Override
    public ResponseDTO<OrderScheduleTimeDRO> getStockScheduleTimes(StockScheduleTimeDIO stockScheduleTimeDIO) {
        logger.info("ZsNormalOrderWorkScheduleRemoteServiceImpl.getStockScheduleTimes stockScheduleTimeDIO={}", stockScheduleTimeDIO);
        try {
            boolean whiteWorkCity = this.isWhiteWorkCity(stockScheduleTimeDIO.getCityId(),stockScheduleTimeDIO.getGeteType());
            // 走老接口
            if (!whiteWorkCity) {
                OrderScheduleDIO orderScheduleDIO = BeanMapper.map(stockScheduleTimeDIO, OrderScheduleDIO.class);
                orderScheduleDIO.setScheDate(DateUtil.toString(stockScheduleTimeDIO.getDutyTime()));
                OrderScheduleVO orderScheduleVO = zsOrderWorkScheduleBService.getScheduleTimes(orderScheduleDIO.getScheDate(), null);
                OrderScheduleTimeDRO orderScheduleTimeDRO = BeanMapper.map(orderScheduleVO, OrderScheduleTimeDRO.class);
                return ResponseDTO.success(orderScheduleTimeDRO);
            }
            StockScheduleTimeBO stockScheduleTimeBO = BeanMapper.map(stockScheduleTimeDIO, StockScheduleTimeBO.class);
            OrderScheduleVO orderScheduleVO = zsOrderWorkStockScheduleBService.getStockScheduleTimes(stockScheduleTimeBO);
            OrderScheduleTimeDRO orderScheduleTimeDRO = BeanMapper.map(orderScheduleVO, OrderScheduleTimeDRO.class);
            return ResponseDTO.success(orderScheduleTimeDRO);
        } catch (Exception e) {
            logger.error("getStockScheduleTimes error={}", e);
            return ResponseDTO.fail(e.getMessage());
        }
    }

    @Override
    public ResponseDTO<List<OrderCartScheduleTimeDRO>> listStockDefaultDutyTime(List<OrderCartStockScheduleDIO> orderScheduleList) {
        logger.info("ZsNormalOrderWorkScheduleRemoteServiceImpl.listOrderCartStockScheduleTime orderScheduleList={}", orderScheduleList);
        if (CollectionUtil.isNullOrEmpty(orderScheduleList)) {
            return ResponseDTO.fail("order cart list dio is empty");
        }

        // 库存白名单
        List<OrderCartStockScheduleDIO> stockWhiteList = new ArrayList<>();
        List<OrderCartScheduleDIO> notStockWhiteList = new ArrayList<>();
        for (OrderCartStockScheduleDIO orderCartStockScheduleDIO : orderScheduleList) {
            if (this.isWhiteWorkCity(orderCartStockScheduleDIO.getCityId(), orderCartStockScheduleDIO.getGeteType())) {
                stockWhiteList.add(orderCartStockScheduleDIO);
            } else {
                notStockWhiteList.add(BeanMapper.map(orderCartStockScheduleDIO, OrderCartScheduleDIO.class));
            }
        }

        // 走新接口
        List<StockDefaultDutyTimeQueryBO> stockDefaultDutyTimeQueries = BeanMapper.mapList(stockWhiteList, StockDefaultDutyTimeQueryBO.class);
        Map<Integer, Date> defaultDutyTimeMap = null;
        try {
            // 只处理三个元素
            if (stockDefaultDutyTimeQueries.size() > 3) {
                stockDefaultDutyTimeQueries = stockDefaultDutyTimeQueries.subList(0, 3);
            }
            defaultDutyTimeMap = zsOrderWorkStockScheduleBService.listStockDefaultDutyTime(stockDefaultDutyTimeQueries);
        } catch (Exception e) {
            logger.info("listStockDefaultDutyTime error={}", e);
            return ResponseDTO.fail(e.getMessage());
        }
        List<OrderCartScheduleTimeDRO> orderCartScheduleTimeDROS = new ArrayList<OrderCartScheduleTimeDRO>();
        for (OrderCartStockScheduleDIO orderCartStockScheduleDIO : stockWhiteList) {
            OrderCartScheduleTimeDRO orderCartScheduleTimeDRO = new OrderCartScheduleTimeDRO();
            orderCartScheduleTimeDRO.setShowProductId(orderCartStockScheduleDIO.getShowProductId());
            orderCartScheduleTimeDRO.setServCategId(orderCartStockScheduleDIO.getServCategId());
            Date date = defaultDutyTimeMap.get(orderCartStockScheduleDIO.getShowProductId());
            if (Objects.isNull(date)) {
                orderCartScheduleTimeDROS.add(orderCartScheduleTimeDRO);
                continue;
            }
            orderCartScheduleTimeDRO.setDutyTime(DateUtil.toString(date));
            orderCartScheduleTimeDRO.setDutyTimestamp(date.getTime());
            orderCartScheduleTimeDROS.add(orderCartScheduleTimeDRO);
        }

        if (CollectionUtil.isNullOrEmpty(notStockWhiteList)) {
            return ResponseDTO.success(orderCartScheduleTimeDROS);
        }

        // 走老接口
        ResponseDTO<List<OrderCartScheduleTimeDRO>> listResponseDTO = this.listOrderCartScheduleTime(notStockWhiteList);
        if (CollectionUtil.isNullOrEmpty(listResponseDTO.getData())) {
            return ResponseDTO.success(orderCartScheduleTimeDROS);
        }
        orderCartScheduleTimeDROS.addAll(listResponseDTO.getData());

        return ResponseDTO.success(orderCartScheduleTimeDROS);
    }

    @Override
    public ResponseDTO<List<GridGroupScheduleCheckDRO>> listGridGroupAvailableEngineer(List<GridGroupScheduleCheckDIO> gridGroupScheduleCheckList) {
        logger.info("listGridGroupAvailableEngineer入参：{}", gridGroupScheduleCheckList);
        try {
            List<GridGroupScheduleCheckDRO> droList = gridGroupDistributeBService.listGridGroupAvailableEngineer(gridGroupScheduleCheckList);
            return ResponseDTO.success(droList);
        } catch (Exception e) {
            logger.error("查询网格组可服务工程师出现异常：", e);
            return ResponseDTO.fail(e.getMessage());
        }
    }

    /**
     * 根据前台产品获取前端产品二级分类
     *
     * @param showProductId
     * @return
     */
    private Integer getShowCategIdByShowProductId(Integer showProductId) {
        Integer showCategId = 0;
        if (NumberUtil.isNullOrZero(showProductId)) {
            return showCategId;
        }

        ProductBaseQuery productDIO = new ProductBaseQuery();
        productDIO.setProductId(showProductId);
        ResponseDTO<List<ProductBaseDRO>> resp = productForeignListRemoteService.listBaseDROByQuery(productDIO);
        logger.info("根据前台产品DIO={},获取前端产品二级分类listBaseDROByDIO resp={}", productDIO, resp);
        List<ProductBaseDRO> productBaseDRO = resp.getData();
        if (CollectionUtil.isNullOrEmpty(productBaseDRO) || !resp.isSuccess()) {
            logger.error("[{}]前台产品不存在", showProductId);
            return null;
        }
        ProductBaseDRO productBase = productBaseDRO.get(0);
        if (Objects.equals(productBase.getShowType(), BaseProductConsts.EC_SHOW_TYPE)) {
            showCategId = productBase.getCategId();
        }
        return showCategId;
    }
}
